package com.yuke.cloud.service.tmc.controller.frontend;

import com.alibaba.fastjson.JSON;
import com.yuke.cloud.common.base.dto.MsgNotificationBody;
import com.yuke.cloud.service.tmc.entity.WebSocketClientMessage;
import com.yuke.cloud.service.tmc.entity.WebSocketServerMessage;
import com.yuke.cloud.service.tmc.service.FeedService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.simp.user.SimpUser;
import org.springframework.messaging.simp.user.SimpUserRegistry;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.security.Principal;
import java.util.Date;

@RestController
@Slf4j
public class WebSocketController {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;
    @Autowired
    private SimpUserRegistry userRegistry;
//    @Autowired
//    private TmcMessageListener tmcMessageListener;

    @Resource
    private FeedService feedService;

    @MessageMapping("/sendTest")   //请求-回应模式，异步；@MessageMapping用于服务端处理客户端发来的STOMP消息，目的地为/app/sendTest,"/app"前缀是隐含的，因为已将其配置为应用的目的地前缀
    @SendTo({"/topic/mubiao1", "/topic/mubiao2"})  //会经过代理(如rabbitmq、activemq等)，然后再发送到 目的地
    public WebSocketServerMessage send(WebSocketClientMessage message) {
        log.info("接收到了消息：" + message.getMsg());
        return new WebSocketServerMessage("客户端发送的消息为：" + message.getMsg());
    }

    @SubscribeMapping("/SubscribeMapping")   //请求-响应模式，同步；不经过代理，执行一次的方法，/app/SubscribeMapping为真实订阅路径，通过如果不加上@SendTo,@SubscribeMapping消息直接返回给用户，
    public WebSocketServerMessage subscribe() {
        log.info("用户订阅了我");
        return new WebSocketServerMessage("感谢您的订阅");
    }

    private SimpMessageSendingOperations messaging;

    @Autowired
    public WebSocketController(SimpMessageSendingOperations messaging) {
        this.messaging = messaging;
    }

    @PostMapping("/mall/feed")
    public void broadcastFeed() {
        log.info("feed");
        //从应用程序的任何部分向连接的客户端发送消息，例发送给订阅/topic/feed的客户端
//        messagingTemplate.convertAndSend("/topic/mubiao1", new WebSocketServerMessage("feed"));
        feedService.broadcastMsg("/topic/mubiao1","这是一条测试的广播消息！");
//        messaging.convertAndSend("/topic/mubiao1", new WebSocketServerMessage("这是由controller发送的一条测试的广播消息！"));
    }

    /**
     * 客户端通过send方式为特定用户指定目的地，最后消息会被发布在 /user/queue/message
     *
     * @param messageClient 消息对象
     * @param stompHeaderAccessor 用户认证信息
     */
    @MessageMapping("/singleUserMsg")
    public void singleUser(WebSocketClientMessage messageClient, StompHeaderAccessor stompHeaderAccessor) {
        String message = messageClient.getMsg();
        log.info("接收到消息：" + message);
        Principal user = stompHeaderAccessor.getUser();
        messaging.convertAndSendToUser(user.getName(), "/queue/message", new WebSocketServerMessage(message));
//        feedService.SendMsgToUser("/queue/message", user.getName(), message);
    }

    @GetMapping("/mall/feedToUser/{userId}")
    public void FeedToUser(@PathVariable String userId) {
        log.info("feedToUser");
//        messagingTemplate.convertAndSend("/topic/mubiao1", new WebSocketServerMessage("feed"));
        feedService.SendMsgToUser("/queue/message", userId, "这是发给用户："+ userId + "的一条测试的广播消息！");
    }

    @MessageMapping("/room-message/{roomId}")
    public void roomMessage(WebSocketClientMessage message, @DestinationVariable String roomId, @Payload String body){
        String englishName = message.getMsg();
        String dest = "/message/" + roomId + "/" + englishName;
        log.info(roomId+"号房间——"+"收到"+ englishName + "  body信息为：" + body);
        this.messagingTemplate.convertAndSend("/topic/feed", new WebSocketServerMessage(englishName));
//        this.messagingTemplate.convertAndSend(dest, message);
    }

    @MessageMapping("/userTest")
    @SendToUser("/queue/message")
    public WebSocketServerMessage userTest(Principal principal, WebSocketClientMessage message) {
        log.info("认证的名字是：{}，收到的消息是：{}", principal.getName(), message.getMsg());
        return new WebSocketServerMessage("userTest");
    }

    @RequestMapping("/templateTest")
    public void templateTest(StompHeaderAccessor stompHeaderAccessor, WebSocketClientMessage message) {
        log.info("当前在线人数：" + userRegistry.getUserCount());
//        log.info(stompHeaderAccessor.getMessage());
        int i = 1;
        for (SimpUser user : userRegistry.getUsers()) {
            log.info("用户：" + i++ + "  ---  " + user);
            log.info("userName : " + user.getName() + ", userSession : " + user.getSessions().toString());
        }
        //发送消息给指定用户

        messagingTemplate.convertAndSendToUser("test", "/queue/message", new WebSocketServerMessage("服务器主动推送的数据"));
    }

    public void templateTest1() {
        messagingTemplate.convertAndSendToUser("test", "/queue/message", new WebSocketServerMessage("服务器主动推送的数据"));
    }

    @MessageMapping("/sendHeartBeat")   //提供给客户端发送心跳用
    public WebSocketServerMessage sendHeartBeat(WebSocketClientMessage message) {
//        log.info("接收到了消息：" + message.getMsg());
        return new WebSocketServerMessage("客户端发送的消息为：" + message.getMsg());
    }

    // for test,mall的请求可以不用进行认证 add by wg 20190103
    @GetMapping("/mall/testSendMsg")
    public void testSendMsg() {
        MsgNotificationBody msgNotificationBody = new MsgNotificationBody();
        msgNotificationBody.setMsgType("orderMsg");
        msgNotificationBody.setWarehouseId(1L);
        msgNotificationBody.setTitle("订单提醒");
        msgNotificationBody.setContent("你有新的订单需要处理！");
        msgNotificationBody.setTime(new Date());
        feedService.broadcastMsg("/topic/queue/ ", JSON.toJSON(msgNotificationBody).toString());

        msgNotificationBody.setMsgType("warehouseMsg");
        msgNotificationBody.setWarehouseId(1L);
        msgNotificationBody.setTitle("调货提醒");
        msgNotificationBody.setContent("你有新的调货请求！");
        msgNotificationBody.setTime(new Date());
        feedService.broadcastMsg("/topic/queue/warehouseMsg", JSON.toJSON(msgNotificationBody).toString());

        msgNotificationBody.setMsgType("shopMsg");
        msgNotificationBody.setWarehouseId(null);
        msgNotificationBody.setTitle("店铺审核");
        msgNotificationBody.setContent("你有新的店铺申请审核！");
        msgNotificationBody.setTime(new Date());
        feedService.broadcastMsg("/topic/queue/shopMsg", JSON.toJSON(msgNotificationBody).toString());
    }

    /**
     * 这里用的是@SendToUser，这就是发送给单一客户端的标志。本例中，
     * 客户端接收一对一消息的主题应该是“/user/” + 用户Id + “/message” ,这里的用户id可以是一个普通的字符串，只要每个用户端都使用自己的id并且服务端知道每个用户的id就行。
     * @return
     */
//    @MessageMapping("/message")
//    @SendToUser("/message")
//    public WebSocketServerMessage handleSubscribe() {
//        System.out.println("this is the @SubscribeMapping('/marco')");
//        return new WebSocketServerMessage("I am a msg from SubscribeMapping('/macro').");
//    }

    /**
     * 表示服务端可以接收客户端通过主题“/app/hello”发送过来的消息，客户端需要在主题"/topic/hello"上监听并接收服务端发回的消息
     *
     */
    @MessageMapping("/hello")
    @SendTo("/topic/hello")
    public WebSocketServerMessage greeting(WebSocketClientMessage message) throws Exception {
        System.out.println("/hello相应"+message.getMsg());
        WebSocketServerMessage webSocketServerMessage = new WebSocketServerMessage();
        webSocketServerMessage.setResponseMessage(message.getMsg());
        return webSocketServerMessage;
    }

    @MessageMapping("/message")
    public void userMessage(WebSocketServerMessage userMessage) throws Exception {
        System.out.println("/message相应"+userMessage.getResponseMessage());
        feedService.SendMsgToUser("/queue/message ","1" ,JSON.toJSON(userMessage.getResponseMessage()).toString());
        messaging.convertAndSendToUser("1", "/queue/message", new WebSocketServerMessage("I am a msg from SubscribeMapping('/macro')."));
        messaging.convertAndSendToUser("1", "/topic/hello", new WebSocketServerMessage("I am a msg from SubscribeMapping('/macro')."));
        messaging.convertAndSendToUser("1", "/message", new WebSocketServerMessage("I am a msg from SubscribeMapping('/macro')."));

        System.out.println(userRegistry.getUsers());
        int i = 1;
        for (SimpUser user : userRegistry.getUsers()) {
            log.info("用户：" + i++ + "  ---  " + user);
            log.info("userName : " + user.getName() + ", userSession : " + user.getSessions().toString());
            messagingTemplate.convertAndSendToUser(user.getName(), "/queue/message", new WebSocketServerMessage("服务器主动推送的数据"+user.getSessions().toString()));

        }
    }




    /**
     * 测试对指定用户发送消息方法
     * @return
     */
    @RequestMapping(path = "/send", method = RequestMethod.GET)
    public WebSocketServerMessage send() {
        messaging.convertAndSendToUser("1", "/message", new WebSocketServerMessage("I am a msg from SubscribeMapping('/macro')."));
        return new WebSocketServerMessage("I am a msg from SubscribeMapping('/macro').");
    }

    @GetMapping("/mall/sendMsgToUser")
    public void sendMsgToUser() {
        MsgNotificationBody msgNotificationBody = new MsgNotificationBody();
        msgNotificationBody.setMsgType("orderMsg");
        msgNotificationBody.setWarehouseId(1L);
        msgNotificationBody.setTitle("订单提醒");
        msgNotificationBody.setContent("你有新的订单需要处理！");
        msgNotificationBody.setTime(new Date());
        System.out.println(msgNotificationBody);
        feedService.SendMsgToUser("/message ","1" ,JSON.toJSON(msgNotificationBody).toString());
    }
}
